package bosVM2.Engine;

import java.io.File;
import java.util.Stack;
import java.util.HashMap;

import bosVM2.Engine.Frames.Frame;
import bosVM2.Engine.Frames.MethodFrame;
import bosVM2.Loader.Translater;
import bosVM2.meta.MetaData;

public class ExecutionEngine implements Runnable {
	Translater t;
	File f;
	//Constructor
	
	public static int counter = 0;
	public ExecutionEngine(File f)
	{
		t = new Translater(this);
		this.f = f;
	}
	
	//MetaData
	private MetaData meta = new MetaData();
	
	public MetaData getMeta()
	{
		return meta;
	}
	
	//Heap
	private Heap H = Heap.getH();
	
	
	//Method storage: currently unused
	public HashMap<String, HashMap<Integer,Object[]>> methodInstructions 
    		= new HashMap<String,HashMap<Integer,Object[]>>();
	
	public HashMap<Integer, Object[]> getInstructions(String s)
	{	
		return new HashMap<Integer,Object[]>(methodInstructions.get(s));
	}
	
	private Stack<Frame> CS = new Stack<Frame>();
	
	public void execute() throws Exception {
		methodInstructions = t.Translate(f);
		//Find a main, executer
		findMains();
		
		while(!(CS.empty()))
		{
			handleIt(CS.pop());
		}
		System.out.print(counter);
		
	}
	private void handleIt(Frame bos) {
		try {
		bos.executeFrame();
		}
		catch( Exception e)
		{
			e.printStackTrace();
			System.err.println("Unknown execution error");
		}
	}

	//Will find all mains, and push them on the CS
	private void findMains() {
		for(String s: meta.getClasses())
		{
			for(String m: meta.getMetaClass(s).getMethods())
			{
				if(m.equals("main"))
				{
					CS.push(new MethodFrame(meta.getMetaClass(s).getMethod(m),null,this));
				}
			}
		}
	}
	@Override
	public void run() {
		try {
			execute();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
	}
}
